package coreBiz

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"errors"
)

type AesCbc struct {
	Key []byte
	Iv  []byte
}

func InitEncryptAesCbcWithKeyIv(Key, Iv string) *AesCbc {
	return &AesCbc{
		Key: []byte(Key),
		Iv:  []byte(Iv),
	}
}

// EncryptCBC 加密
func (a *AesCbc) EncryptCBC(content string) string {
	if len(a.Key) != 16 {
		return ""
	}

	// 创建AES加密器
	block, err := aes.NewCipher(a.Key)
	if err != nil {
		return ""
	}

	// 对明文进行补码
	paddingText := a.pkcs7Padding([]byte(content))

	// 创建CBC加密器
	cbc := cipher.NewCBCEncrypter(block, a.Iv)

	// 加密明文
	ciphertext := make([]byte, len(paddingText))
	cbc.CryptBlocks(ciphertext, paddingText)

	// 将密文进行Base64编码
	return base64.StdEncoding.EncodeToString(ciphertext)
}

func (a *AesCbc) DecryptCBC(content string) (string, error) {
	if len(a.Key) != 16 {
		return "", errors.New("key wrong")
	}
	encrypted, err := base64.StdEncoding.DecodeString(content)
	if err != nil {
		return "", err
	}
	block, err := aes.NewCipher(a.Key)
	if err != nil {
		return "", err
	}

	// 创建 CBC 模式实例
	mode := cipher.NewCBCDecrypter(block, a.Iv)

	// 解密
	decrypted := make([]byte, len(encrypted))
	mode.CryptBlocks(decrypted, encrypted)

	// 去除 PKCS7 填充
	decrypted, err = a.pkcs7UnPadding(decrypted)
	if err != nil {
		return "", err
	}
	return string(decrypted), nil
}

// pkcs7 padding 填充函数
func (a *AesCbc) pkcs7Padding(data []byte) []byte {
	// 对明文进行补码
	paddingSize := aes.BlockSize - len(data)%aes.BlockSize
	return append(data, bytes.Repeat([]byte{byte(paddingSize)}, paddingSize)...)
}

// pkcs7 padding 去除填充函数
func (a *AesCbc) pkcs7UnPadding(data []byte) ([]byte, error) {

	if len(data) == 0 {
		return nil, nil
	}
	//防止解密出错崩溃
	unPadding := int(data[len(data)-1])
	if unPadding > len(data) {
		return nil, errors.New("unPadding error")
	}

	return data[:(len(data) - unPadding)], nil
}
